﻿/*!
 * Copyright (c), 上海沃恩信息科技有限公司.
 * All rights reserved.
 * Licensed under BSD (https://www.pittypat.work/bsd.html).
 */

using System.Threading.Tasks;

namespace Pittypat.Web
{
    /// <summary>
    /// 处理对功能的请求。
    /// </summary>
    static class FunctionHttpHandler
    {
        /// <summary>
        /// 设置指定功能的 FunctionModel 的参数值。
        /// </summary>
        /// <param name="funcModel">目标 FunctionModel 对象实例。</param>
        /// <param name="meta">功能的元数据信息。</param>
        /// <param name="funcPath">功能的路径。</param>
        /// <param name="request">当前请求对象。</param>
        internal static void SetupFuncModel(object funcModel, FunctionMeta meta, string funcPath, Request request)
        {
            // 请求中包含的用户信息
            var user = request.User;

            // 当前功能的上下文
            dynamic d = funcModel;

            // 设置功能路径
            d.Path = funcPath;
            // 设置当前用户
            d.User = user;

            // FunctionModel.Args 属性对象
            FunctionArgs args = d.Args;

            foreach (var param in meta.Parameters)
            {
                if (param.IsPrimitive)
                {
                    if (param.Role == ParameterRole.UserId)
                    {
                        // 设置参数列表中的用户 Id
                        args[param.Identifier] = user.Id;
                    }
                    else
                    {
                        // 从请求表单字段列表中查找和设置参数值
                        args[param.Identifier] = request.Form[param.Identifier].To(param.DataType);
                    }
                }
            }
        }

        /// <summary>
        /// 异步处理指定的请求。
        /// </summary>
        /// <param name="request">要处理的请求。</param>
        /// <returns>结果消息。</returns>
        internal static async Task<Message> ProcessAsync(Request request)
        {
            // 请求对应的功能信息
            var funcInfo = request.FuncInfo;

            // 设置 funcModel 的参数值
            SetupFuncModel(funcInfo.FunctionModel, funcInfo.Meta, funcInfo.Path, request);

            // 异步执行目标功能
            var task = (Task)funcInfo.Method.Invoke(funcInfo.Module, new object[] { funcInfo.FunctionModel, request.Progress });

            // 等待异步任务完成
            await task;

            dynamic d = funcInfo.FunctionModel;
            if (d.Success)
            {
                // 功能 Api 执行成功，返回 Api 的返回值，一个 IJson 对象
                d = task;
                return Message.Create((IJson)d.Result);
            }
            else
            {
                // 功能 Api 执行失败，返回失败消息
                return Message.Create((string)(@string)d.Message);
            }
        }
    }
}
